package com.st.rzs.redis.service.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.st.rzs.redis.service.IRedisClient;
import com.st.rzs.redis.util.ConfigUtil;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisShardInfo;
import redis.clients.jedis.ShardedJedis;
import redis.clients.jedis.ShardedJedisPipeline;
import redis.clients.jedis.ShardedJedisPool;


class QueueObject {
	Object object;
	int seconds;

	public QueueObject(Object object, int seconds) {
		this.object = object;
		this.seconds = seconds;
	}

	public Object getObject() {
		return object;
	}

	public int getSeconds() {
		return seconds;
	}
}

public class RedisClientManager implements IRedisClient {

	private static final Log logger = LogFactory.getLog(RedisClientManager.class.getName());

	private ShardedJedisPool sentinelPool;// 切片连接池

	private static String sentinels = ConfigUtil.getString("config.properties", "redis.config.sentinels", "127.0.0.1");
	private static String name = ConfigUtil.getString("config.properties", "redis.config.masters", "master");

	public RedisClientManager() {
		this(sentinels, name);
	}

	public static final int QUEUE_MAX_SIZE = 100000;

	public static int timeOut = 10000;

	public RedisClientManager(String sentinels, String name) {
		List<JedisShardInfo> shards = new ArrayList<JedisShardInfo>();
		String[] split = sentinels.split(",");
		for (String str : split) {
			String host = str.split(":")[0];
			int port = Integer.parseInt(str.split(":")[1]);
			shards.add(new JedisShardInfo(host, port, name));
		}
		this.sentinelPool = new ShardedJedisPool(new JedisPoolConfig(), shards);
	}

	private void input(String key, Object obj, int seconds) {

		ShardedJedis shardedJedis = sentinelPool.getResource();
		ShardedJedisPipeline pipe = shardedJedis.pipelined();

		if (obj instanceof String) {
			pipe.set(key, obj.toString());
		} else if (obj instanceof List) {
			List<String> value = (List<String>) obj;
			String[] data = new String[value.size()];
			pipe.rpush(key, value.toArray(data));

		} else if (obj instanceof Set) {
			Set<String> value = (Set<String>) obj;
			String[] data = new String[value.size()];
			pipe.sadd(key, value.toArray(data));

		} else if (obj instanceof Map) {
			Map<String, String> value = (Map<String, String>) obj;
			pipe.hmset(key, value);
		}

		if (seconds > 0) {
			pipe.expire(key, seconds);
		}
		pipe.sync();
		if (shardedJedis != null)
			sentinelPool.returnResource(shardedJedis);
	}

	@Override
	public boolean containsKey(String key) {

		boolean result = false;
		ShardedJedis shardedJedis = sentinelPool.getResource();
		try {
			result = shardedJedis.exists(key);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (shardedJedis != null)
				sentinelPool.returnResource(shardedJedis);
		}
		return result;
	}

	@Override
	public boolean addObject(String key, List<String> value) {

		input(key, value, -1);
		return true;
	}

	@Override
	public boolean addObject(String key, List<String> value, int seconds) {

		input(key, value, seconds);
		return true;
	}

	@Override
	public boolean addObject(String key, Set<String> value) {

		input(key, value, -1);
		return true;
	}

	@Override
	public boolean addObject(String key, Set<String> value, int seconds) {

		input(key, value, seconds);
		return true;
	}

	@Override
	public boolean addObject(String key, Map<String, String> value) {

		input(key, value, -1);
		return true;
	}

	@Override
	public boolean addObject(String key, Map<String, String> value, int seconds) {

		input(key, value, seconds);
		return true;
	}

	@Override
	public boolean setObject(String key, String value) {

		input(key, value, -1);
		return true;
	}

	@Override
	public boolean setObject(String key, String value, int seconds) {

		input(key, value, seconds);
		return true;
	}

	@Override
	public boolean setObject(String key, List<String> value) {

		return addObject(key, value);
	}

	@Override
	public boolean setObject(String key, List<String> value, int seconds) {

		return addObject(key, value, seconds);
	}

	@Override
	public boolean setObject(String key, Set<String> value) {

		return addObject(key, value);
	}

	@Override
	public boolean setObject(String key, Set<String> value, int seconds) {
		return addObject(key, value, seconds);
	}

	@Override
	public boolean setObject(String key, Map<String, String> value) {

		return addObject(key, value);
	}

	@Override
	public boolean setObject(String key, Map<String, String> value, int seconds) {
		return addObject(key, value, seconds);
	}

	@Override
	public boolean removeObject(String key) {

		boolean result = false;
		ShardedJedis shardedJedis = sentinelPool.getResource();
		try {
			shardedJedis.del(key);
			result = true;
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (shardedJedis != null)
				sentinelPool.returnResource(shardedJedis);
		}
		return result;
	}

	@Override
	public Object getObject(String key) {

		Object result = null;
		ShardedJedis shardedJedis = sentinelPool.getResource();
		try {
			String type = shardedJedis.type(key);
			switch (type) {
			case TYPE_NONE:
				break;
			case TYPE_STRING:
				result = shardedJedis.get(key);
				break;
			case TYPE_LIST:
				result = shardedJedis.lrange(key, 0, -1);
				break;
			case TYPE_SET:
				result = shardedJedis.smembers(key);
				break;
			case TYPE_HASH:
				result = shardedJedis.hgetAll(key);
				break;
			default:
				break;
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (shardedJedis != null)
				sentinelPool.returnResource(shardedJedis);
		}
		return result;
	}

	@Override
	public String getObject(String key, String fieldName) {

		String result = null;
		ShardedJedis shardedJedis = sentinelPool.getResource();
		try {
			result = shardedJedis.hget(key, fieldName);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (shardedJedis != null)
				sentinelPool.returnResource(shardedJedis);
		}
		return result;
	}

}
